package main

func main() {
	/*
		并发性：
			1.多任务：操作系统可以同时运行多个任务

			2.串行：
				|A       |B      |C
				 ———————— ——————— ———————————
			  并行：程序在 任意时刻 都是同时运行的
				具有瞬时性，在于执行
				A ——————
				B ——————
				C ——————
			  并发：程序在 单位时间 内是同时运行的
				（规定时间内，多个请求都得到执行和处理，内部可能是分时操作的）
				具有过程性，在于结构
				A -  -  -
				B  -  -  -
				C   -  -  -

			3.进程：
				一个程序在一个数据集中的一次动态执行，可以简单理解为“正在执行的程序”，它是CPU资源分配和调度的独立单位
					eg：一台电脑同时在运行QQ、微信、浏览器、Goland、文档编写。。。 而每一个就叫是一个进程
				（1）一般由 程序、数据集、进程控制块 三部分组成
				     程序：我们编写的程序用来描述进程要完成那些功能以及如何完成
				    数据集：程序在执行过程中所需要使用的资源
				 进程控制块：用来记录进程的外部特征，描述进程的执行变化过程，系统可以用它来控制和管理进程，它是系统感知进程存在的唯一标志
				（2）进程的局限：创建、撤销和切换的开销比较大

			  线程：也叫轻量级进程
				一个基本的CPU执行单元，也是程序执行过程中最小单元
					eg：编写文档时，有错别字查找、首字母大写。。。 这就相当于是两条线程
				（1）由 线程ID、程序计数器、寄存器集合和堆栈 共同组成。
				（2）一个进程可以包含多个线程，至少有一个线程（称为主线程）
					如果一个进程结束了，那么这个线程也就结束了
					但是一个线程结束了，这个进程并不会结束，只有所有的线程都结束了，这个进程才会结束
				（3）进程的优点：减小了程序并发执行时的开销，提高了操作系统的并发性能
					进程的缺点：线程没有自己的相同资源，只拥有在运行时必不可少的资源
					但同一进程的各线程可以共享进程所拥有的系统资源

			  协程：
				一种用户态的轻量级线程，又称微线程。
				（1）协程的调度完全有用户控制
				（2）与传统的系统级线程和进程相比，协程的最大优势是“轻量级”，可以轻松创建上百万个儿不会导致系统资源衰竭，而线程和进程通常最多也不能超过 1 万的。
				（3）协程拥有自己的寄存器上下文和栈。

			4.goroutine
				goroutine 是 go语言特有的名词，区别于进程、线程、协程。
				goroutine 可以被认为是轻量级的线程，是 Go 中的并发执行体
			 （1）主goroutine：封装 main函数 的 goroutine
				主goroutine涉及的工作内容：
				 1.创建一个特殊的 defer 语句，用于在主 goroutine 退出时做必要的售后处理。
				 2.启动专用于在后台清扫内存垃圾的 goroutine，并设置GC可用的标识
				 3.执行 main包 中的 init函数
				 4.执行 main函数
					执行完main函数后，还会检查主 goroutine 是否引发了运行时恐慌，并进行必要的处理。
					最后会结束自己以及当前进程的运行
			 （2）使用goroutine：
					go + 函数
				go 关键字后面必须跟一个函数，不能是语句或其他东西，函数的返回值会被忽略

			 （3）runtime.NumGoroutine() 返回当前程序的goroutine的数量

			 （4）goroutine的特性：
				1.go 的执行是非阻塞的
				2.go 后面的函数的返回值会被忽略
				3.调度器不保证多个goroutine的执行次序
				4.所有 goroutine 是平等地被调度和执行的
				5.Go 在执行时会单独为 main 函数创建一个 goroutine
				6.不能在一个 goroutine 里显示地操作另一个 goroutine

			 （5）func GOMAXPROCS(n int) int：
					设置或查询可以并发执行的 goroutine 数目
						n > 1：设置 GOMAXPROCS 值
						n <= 1：查询当前 GOMAXPROCS 值

				 func Goexit()：
					结束当前 goroutine 的运行
					结束前会调用已注册的“defer”

				 func Gosched()：
					放弃当前调度执行机会，将当前 goroutine 放在队列中等待下次被调度

			5.多进程模型：
				优点：（1）每个进程都有自己独立的内存空间
					 （2）隔离性好、健壮性高
				缺点：（1）进程比较重，进程的切换消耗较大
					 （2）进程间的通信需要多次在内核区和用户区之间复制数据

			  多线程模型：
				优点：通过共享内存进行通信，更快捷，切换代价更小
				缺点：多个线程共享内存空间，极易导致数据访问混乱，某个线程误操作内存挂掉可能危及整个线程组，健壮性不高

			6.线程模型：
				KSE：内核级线程
				 OS：操作系统内核。
					是一个计算机操作系统中最重要也是最核心的部分。它是操作系统的基础，提供了各种资源和服务的管理和分配，同时也是应用程序与计算机硬件之间的接口。
			（1）内核级线程模型：
					用户线程 与 KSE（内核线程） 是 1 对 1 关系(1:1)。
				  大部分的编程语言的线程库都是对操作系统的线程（内核级线程）的一层封装，创建出来的每个线程与一个不同的KSE静态关联。
				因此，其调度完全由 OS 调度器来做

				优点：在多核处理器的硬件支持下，内核空间线程模型支持了真正的并行，当一个线程被阻塞后，允许另一个线程继续执行，所以并发能力比较强
				缺点：每创建一个用户级线程都需要创建一个内核级线程与其对应，这样创建线程的开销比较大，会影响到应用程序的性能

			（2）用户级线程模型：
					用户线程 与 KSE（内核线程） 是多对 1 关系(M:1)。
				  这种协程的创建、销毁以及多个线程之间的协调等操作都是由用户自己实现的线程库来负责，
				对 OS 内核透明，一个进程中所有创建的线程都与同一个 KSE 在运行时动态关联。现在有许多语言实现的 协程 基本上都是属于这种方式

				优点：线程上下文切换都发生1在用户空间，避免模态切换，从而对性能有积极的影响
				缺点：所有的线程基于一个内核调度实体即内核线程，这意味着只有一个处理器可以被利用，在多处理器环境下这是不能被接受的。
					本质上，用户线程只解决了并发问题，但是没有解决并行问题。如果线程因为 I/O 操作陷入了内核态，内核态线程阻塞等待 I/O 数据，
					则所有的线程都将会被阻塞，用户空间也可以使用非阻塞而 I/O，但是不能避免性能及复杂度问题。

			（3）两级线程模型：
					用户线程 与 KSE（内核线程） 是多对多关系(M:N)。
				  这种实现综合了前面两种模型的优点，为一个进程中创建多个 KSE，并且线程可以与不同的 KSE 在运行时进行动态关联，
				当某个 KSE 由于其上工作的线程的阻塞操作被内核调度出 CPU 时，当前与其关联的其余用户线程可以重新与其他 KSE 建立关联关系

				缺点：这种动态关联机制的实现很复杂，也需要用户自己去实现。

				此模型有时也被称为 混合型线程模型，即用户调用器实现用户线程到 KSE 的调度，内核调度器实现 KSE 到 CPU 上的调度

			7.Sched结构：调度器，它维护有存储 M 和 G 的队列以及调度器的一些状态信息等。
			  M：内核线程
			  P：M 运行 G 时所需要的资源
			  G：goroutine
			注：
			（1）M 是操作系统层面调度和执行的实体
			（2）P 是对资源的一种抽象和管理，不是一段代码实体，而是一个管理的数据结构
			（3）G 是 Go 运行时对 goroutine的抽象描述，只是一个数据结构，并不是执行实体，所以 G 可以复用。
				G 中存放并发执行的代码入口地址、上下文、运行环境（关联的P和M）、运行栈等相关的元信息
			（4）G 和 P 是一种 M:N的关系
			（5）在同一个 CPU 上的 M：并发
				在不同的 CPU 上的 M：并行
					M			M
					|			|
					P——G		P——G
					|  |		|  |
					G  G		G  G
					   |		   |
					   G		   G

			8.线程阻塞：
				当正在运行的goroutine阻塞时，例如进行系统调度，会在创建一个系统线程M1，当前的线程(M)放弃了它的(P)，P转到新的线程(M)中去运行

			9.runqueue执行完成：
				当其中一个 P 的 runqueue 为空，没有 goroutine 可以调度，它会从另外一个上下文偷取一半的 goroutine
					M		M			M		M
					|		|			|		|
					P——G	P	————>	P——G	P——G
					|  |				|		|
					G  Gm				G		Gm
					   |
					   G
	*/
}
